#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自定义设备录音模块
Custom Device Recording Module

支持非标准音频设备（如串口设备）的录音功能
Supports recording from non-standard audio devices (like serial devices)
"""

import os
import sys
import time
import threading
import logging
from typing import Optional, Callable

class CustomDeviceRecorder:
    """
    自定义设备录音器
    Custom Device Recorder
    
    专门用于处理非标准音频设备，如 /dev/myspeech
    Specifically designed for non-standard audio devices like /dev/myspeech
    """
    
    def __init__(self, device_path: str = "/dev/myspeech", **kwargs):
        """
        初始化自定义设备录音器
        Initialize custom device recorder
        
        Args:
            device_path: 设备路径 / Device path
        """
        self.device_path = device_path
        self.logger = logging.getLogger(__name__)
        
        # 录音状态
        self.is_recording = False
        self.stop_event = threading.Event()
        
        # 回调函数
        self.start_callback: Optional[Callable] = None
        self.stop_callback: Optional[Callable] = None
        self.speech_detected_callback: Optional[Callable] = None
        
        # 检查设备是否存在
        if not os.path.exists(device_path):
            raise FileNotFoundError(f"Device {device_path} not found")
            
        # 检查设备权限
        if not os.access(device_path, os.R_OK | os.W_OK):
            raise PermissionError(f"No read/write permission for {device_path}")
            
        self.logger.info(f"CustomDeviceRecorder initialized with device: {device_path}")
    
    def set_callbacks(self, start_callback=None, stop_callback=None, speech_detected_callback=None):
        """
        设置回调函数
        Set callback functions
        """
        self.start_callback = start_callback
        self.stop_callback = stop_callback
        self.speech_detected_callback = speech_detected_callback
    
    def record_blocking(self, output_path: str, timeout: Optional[float] = None) -> Optional[str]:
        """
        阻塞式录音
        Blocking recording
        
        Args:
            output_path: 输出文件路径 / Output file path
            timeout: 超时时间 / Timeout
            
        Returns:
            str: 录音文件路径，失败返回None / Recording file path, None if failed
        """
        self.is_recording = True
        start_time = time.time()
        
        # 调用开始回调
        if self.start_callback:
            try:
                self.start_callback()
            except Exception as e:
                self.logger.error(f"Error in start callback: {e}")
        
        try:
            # 确保输出目录存在
            os.makedirs(os.path.dirname(output_path), exist_ok=True)
            
            # 打开设备进行读取
            with open(self.device_path, 'rb') as device:
                with open(output_path, 'wb') as output_file:
                    self.logger.info(f"Started recording from {self.device_path} to {output_path}")
                    
                    # 调用语音检测回调（假设开始就有语音）
                    if self.speech_detected_callback:
                        try:
                            self.speech_detected_callback()
                        except Exception as e:
                            self.logger.error(f"Error in speech detected callback: {e}")
                    
                    while True:
                        # 检查停止事件
                        if self.stop_event.is_set():
                            self.logger.info("Recording stopped by stop event")
                            break
                            
                        # 检查超时
                        if timeout and (time.time() - start_time) > timeout:
                            self.logger.info(f"Recording stopped due to timeout ({timeout}s)")
                            break
                        
                        try:
                            # 从设备读取数据
                            data = device.read(1024)  # 每次读取1KB
                            if data:
                                output_file.write(data)
                            else:
                                # 如果没有数据，短暂等待
                                time.sleep(0.01)
                                
                        except Exception as e:
                            self.logger.error(f"Error reading from device: {e}")
                            break
            
            self.is_recording = False
            
            # 调用停止回调
            if self.stop_callback:
                try:
                    self.stop_callback()
                except Exception as e:
                    self.logger.error(f"Error in stop callback: {e}")
            
            self.logger.info(f"Recording completed: {output_path}")
            return output_path
            
        except Exception as e:
            self.logger.error(f"Recording failed: {e}")
            self.is_recording = False
            return None
    
    def record_non_blocking(self, output_path: str, timeout: Optional[float] = None) -> threading.Thread:
        """
        非阻塞式录音
        Non-blocking recording
        
        Args:
            output_path: 输出文件路径 / Output file path
            timeout: 超时时间 / Timeout
            
        Returns:
            threading.Thread: 录音线程 / Recording thread
        """
        def record_thread():
            self.record_blocking(output_path, timeout)
        
        thread = threading.Thread(target=record_thread)
        thread.daemon = True
        thread.start()
        return thread
    
    def stop_recording(self):
        """
        停止录音
        Stop recording
        """
        self.logger.info("Stopping recording...")
        self.stop_event.set()
        
        # 等待录音结束
        timeout = 5.0  # 5秒超时
        start_time = time.time()
        while self.is_recording and (time.time() - start_time) < timeout:
            time.sleep(0.1)
        
        if self.is_recording:
            self.logger.warning("Recording did not stop within timeout")
        else:
            self.logger.info("Recording stopped successfully")
        
        self.stop_event.clear()
    
    def test_device(self) -> bool:
        """
        测试设备是否可用
        Test if device is available
        
        Returns:
            bool: 设备是否可用 / Whether device is available
        """
        try:
            with open(self.device_path, 'rb') as device:
                # 尝试读取少量数据
                device.read(1)
                return True
        except Exception as e:
            self.logger.error(f"Device test failed: {e}")
            return False

# 测试函数
def test_custom_device_recorder():
    """
    测试自定义设备录音器
    Test custom device recorder
    """
    logging.basicConfig(level=logging.INFO)
    
    try:
        recorder = CustomDeviceRecorder("/dev/myspeech")
        
        # 测试设备
        if recorder.test_device():
            print("✓ Device test passed")
        else:
            print("✗ Device test failed")
            return
        
        # 设置回调
        def on_start():
            print("Recording started")
        
        def on_stop():
            print("Recording stopped")
        
        def on_speech():
            print("Speech detected")
        
        recorder.set_callbacks(on_start, on_stop, on_speech)
        
        # 测试录音
        output_path = "./test_recording.raw"
        print(f"Starting 5-second test recording to {output_path}")
        
        result = recorder.record_blocking(output_path, timeout=5.0)
        
        if result:
            print(f"✓ Recording successful: {result}")
            if os.path.exists(result):
                size = os.path.getsize(result)
                print(f"  File size: {size} bytes")
        else:
            print("✗ Recording failed")
            
    except Exception as e:
        print(f"✗ Test failed: {e}")

if __name__ == "__main__":
    test_custom_device_recorder()